home *** CD-ROM | disk | FTP | other *** search
/ SGI Hot Mix 17 / Hot Mix 17.iso / HM17_SGI / research / lib / ladfit.pro < prev    next >
Text File  |  1997-07-08  |  6KB  |  177 lines

  1. ;$Id: ladfit.pro,v 1.9 1997/01/15 03:11:50 ali Exp $
  2. ;
  3. ; Copyright (c) 1994-1997, Research Systems, Inc.  All rights reserved.
  4. ;       Unauthorized reproduction prohibited.
  5. ;+
  6. ; NAME:
  7. ;       LADFIT
  8. ;
  9. ; PURPOSE:
  10. ;       This function fits the paired data {X(i), Y(i)} to the linear model,
  11. ;       y = A + Bx, using a "robust" least absolute deviation method. The 
  12. ;       result is a two-element vector containing the model parameters, A 
  13. ;       and B.
  14. ;
  15. ; CATEGORY:
  16. ;       Statistics.
  17. ;
  18. ; CALLING SEQUENCE:
  19. ;       Result = LADFIT(X, Y)
  20. ;
  21. ; INPUTS:
  22. ;       X:    An n-element vector of type integer, float or double.
  23. ;
  24. ;       Y:    An n-element vector of type integer, float or double.
  25. ;
  26. ; KEYWORD PARAMETERS:
  27. ;  ABSDEV:    Use this keyword to specify a named variable which returns the
  28. ;             mean absolute deviation for each data-point in the y-direction.
  29. ;
  30. ;  DOUBLE:    If set to a non-zero value, computations are done in double 
  31. ;             precision arithmetic.
  32. ;
  33. ; EXAMPLE:
  34. ;       Define two n-element vectors of paired data.
  35. ;         x = [-3.20, 4.49, -1.66, 0.64, -2.43, -0.89, -0.12, 1.41, $
  36. ;               2.95, 2.18,  3.72, 5.26]
  37. ;         y = [-7.14, -1.30, -4.26, -1.90, -6.19, -3.98, -2.87, -1.66, $
  38. ;              -0.78, -2.61,  0.31,  1.74]
  39. ;       Compute the model parameters, A and B.
  40. ;         result = ladfit(x, y, absdev = absdev)
  41. ;       The result should be the two-element vector:
  42. ;         [-3.15301, 0.930440]
  43. ;       The keyword parameter should be returned as:
  44. ;         absdev = 0.636851
  45. ;
  46. ; REFERENCE:
  47. ;       Numerical Recipes, The Art of Scientific Computing (Second Edition)
  48. ;       Cambridge University Press
  49. ;       ISBN 0-521-43108-5
  50. ;
  51. ; MODIFICATION HISTORY:
  52. ;       Written by:  GGS, RSI, September 1994
  53. ;       Modified:    GGS, RSI, July 1995
  54. ;                    Corrected an infinite loop condition that occured when
  55. ;                    the X input parameter contained mostly negative data.
  56. ;       Modified:    GGS, RSI, October 1996
  57. ;                    If least-absolute-deviation convergence condition is not
  58. ;                    satisfied, the algorithm switches to a chi-squared model.
  59. ;                    Modified keyword checking and use of double precision.
  60. ;       Modified:    GGS, RSI, November 1996
  61. ;                    Fixed an error in the computation of the median with
  62. ;                    even-length input data. See EVEN keyword to MEDIAN.
  63. ;-
  64.  
  65. FUNCTION Sign, z, d
  66.   RETURN, ABS(z) * d / ABS(d)
  67. END
  68.  
  69. FUNCTION MDfunc, b, x, y, arr, aa, absdev, nX, Double = Double
  70.   ON_ERROR, 2
  71.   eps = 1.0e-7
  72.   arr = y - b*x
  73.   if nX MOD 2 eq 0 then $ ;X is of even length.
  74.     ;j = nX / 2
  75.     ;Average Kth and K-1st medians.
  76.     aa = MEDIAN(arr, /EVEN) $
  77.   else aa = MEDIAN(arr)
  78.   sum = 0
  79.   absdev = 0
  80.  
  81.   ;for k = 0L, nX-1 do begin
  82.   ;  d = y(k) - (b * x(k) + aa)
  83.   ;  absdev = absdev + abs(d)
  84.   ;  if y(k) ne 0 then d = d / abs(y(k))
  85.   ;  if abs(d) gt eps then sum = sum + Sign(x(k), d)
  86.   ;endfor
  87.  
  88.   d = y - (b * x + aa)
  89.   absdev = TOTAL(abs(d), Double = Double)
  90.   zeros = where(y ne 0)
  91.   d = d[zeros] / abs(y[zeros])  
  92.   zeros = where(abs(d) gt eps, nzeros)
  93.   if nzeros ne 0 then $
  94.     sum = TOTAL(x[zeros]*Sign(REPLICATE(1.0, nzeros), d[zeros]), $
  95.                                                  Double = Double)
  96.   if Double eq 0 then RETURN, FLOAT(sum) else RETURN, sum
  97. END
  98.  
  99. FUNCTION MDfunc2, x, y, nX, Double = Double
  100.   ON_ERROR, 2
  101.   ss = nX + 0.0
  102.   sx = TOTAL(x, Double = Double)
  103.   sy = TOTAL(y, Double = Double)
  104.   t = x - sx/ss
  105.   st2 = TOTAL(t^2, Double = Double)
  106.   b = TOTAL(t * y, Double = Double)
  107.   b = b / st2
  108.   a = (sy - sx * b) / ss
  109.   sdeva = sqrt((1.0 + sx * sx / (ss * st2)) / ss)
  110.   sdevb = sqrt(1.0 / st2)
  111.   chisqr = TOTAL( (y - a - b * x)^2, Double = Double )
  112.   prob = 1.0
  113.   sdevdat = sqrt(chisqr / (nX-2))
  114.   sdeva = sdeva * sdevdat
  115.   sdevb = sdevb * sdevdat
  116.   sig_ab = [sdeva, sdevb]
  117.   if Double eq 0 then RETURN, FLOAT([a, b]) else RETURN, [a, b]
  118. END
  119.  
  120. FUNCTION LadFit, x, y, absdev = absdev, Double = Double
  121.   ON_ERROR, 2
  122.  
  123.   TypeX = SIZE(X)
  124.   TypeY = SIZE(Y)
  125.   nX = TypeX[TypeX[0]+2]
  126.   nY = TypeY[TypeY[0]+2]
  127.  
  128.   if nX ne nY then $
  129.     MESSAGE, "X and Y must be vectors of equal length."
  130.  
  131.   ;If the DOUBLE keyword is not set then the internal precision and
  132.   ;result are identical to the type of input.
  133.   if N_ELEMENTS(Double) eq 0 then $
  134.     Double = (TypeX[TypeX[0]+1] eq 5 or TypeY[TypeY[0]+1] eq 5)
  135.  
  136.   sx = TOTAL(x, Double = Double)
  137.   sy = TOTAL(y, Double = Double)
  138.   sxy = TOTAL(x*y, Double = Double)
  139.   sxx = TOTAL(x*x, Double = Double)
  140.   del = nX * sxx - sx^2
  141.   aa = (sxx * sy - sx * sxy) / del
  142.   bb = (nX * sxy - sx * sy) / del
  143.   chisqr = TOTAL((y - (aa + bb*x))^2, Double = Double)
  144.   sigb = sqrt(chisqr / del)
  145.   b1 = bb
  146.   f1 = MDfunc(b1, x, y, arr, aa, absdev, nX, Double = Double)
  147.   if f1 eq 0 then RETURN, MDfunc2(x, y, nX, Double = Double)
  148.   b2 = bb + Sign(3.0 * sigb, f1) 
  149.   f2 = MDfunc(b2, x, y, arr, aa, absdev, nX, Double = Double)
  150.   while f1*f2 gt 0 do begin
  151.     bb = 2.0 * b2 - b1
  152.     b1 = b2
  153.     f1 = f2
  154.     b2 = bb
  155.     f2 = MDfunc(b2, x, y, arr, aa, absdev, nX, Double = Double)
  156.   endwhile
  157.   sigb = 0.01 * sigb
  158.   while abs(b2-b1) gt sigb do begin
  159.     bb = 0.5 * (b1 + b2)
  160.     if bb eq b1 or bb eq b2 then begin
  161.       absdev = absdev / nX
  162.       if Double eq 0 then RETURN, FLOAT([aa, bb]) else RETURN, [aa, bb]
  163.     endif else begin
  164.       f = MDfunc(bb, x, y, arr, aa, absdev, nX, Double = Double)
  165.       if f*f1 ge 0 then begin
  166.         f1 = f
  167.         b1 = bb
  168.       endif else begin
  169.         f2 = f
  170.         b2 = bb
  171.       endelse
  172.     endelse
  173.   endwhile
  174.   absdev = absdev / nX
  175.   if Double eq 0 then RETURN, FLOAT([aa, bb]) else RETURN, [aa, bb]
  176. END
  177.